﻿using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using SeeSharpTools.JY.GUI;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Linq;

namespace OTA上位机
{
    public partial class Form1 : Form
    {
        public enum MachineState
        {
            E_START_TX,
            E_START_RX,
            E_IDLE,
        }

        MachineState status = MachineState.E_IDLE;
        string port = "";
        string baudRate = "";
        string filePath = "";
        int filesize = 0;
        internal const string HeadInfo = "1###";
        internal const string HeadReq = "2###";
        internal const string HeadData = "3###";
        internal const string DefPort = "com1";
        internal const string DefBaudRate = "115200";


        // 相对路径，配置文件将位于exe同目录下
        string uartConfigPath = Path.Combine(Application.StartupPath, "uartConfig.txt");

        // 相对路径，配置文件将在 exe目录\configs\config.txt
        // string configPath = Path.Combine(Application.StartupPath, "configs", "config.txt");

        string binConfigPath = Path.Combine(Application.StartupPath, "binConfig.txt");
        private bool configFileExist()
        {
            if (File.Exists(uartConfigPath))
            {
                return true;
            }
            else
            {
                Console.WriteLine("文件\"" + uartConfigPath + "\"不存在");
                return false;
            }
        }

        private void configFile(string p,string b)
        {
            // 获取配置文件所在的目录路径
            string configDir = Path.GetDirectoryName(uartConfigPath);

            // 确保目录存在，如果不存在则创建
            if (!Directory.Exists(configDir))
            {
                Directory.CreateDirectory(configDir);
                Console.WriteLine("已创建文件夹: " + configDir);
            }

            JObject rootJ = new JObject();
            rootJ["port"] = p;
            rootJ["baudRate"] = b;
            string configtxt = rootJ.ToString();

            FileStream fs = new FileStream(uartConfigPath, FileMode.Create, FileAccess.Write); // 创建
            StreamWriter sw = new StreamWriter(fs);
            sw.Write(configtxt);
            sw.Close();
            fs.Close();
        }

        public Form1()
        {
            InitializeComponent();
            button2.Enabled = true;
            button4.Enabled = false;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            if (configFileExist() == false)
            {
                configFile(DefPort, DefBaudRate);
            }

            string configtxt = File.ReadAllText(uartConfigPath, System.Text.Encoding.ASCII); // 读取全部内容,编码格式
            string json = configtxt;

            Dictionary<string, string> values = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);

            port = values["port"];
            baudRate = values["baudRate"];

            //GUI更新
            this.textBox2.Text = port;
            this.textBox3.Text = baudRate;
            this.progressBar1.Value = 0;

            /***********************依葫芦画瓢*********************/


            if (File.Exists(binConfigPath))
            {
                // 文件存在，读取内容
                string content = File.ReadAllText(binConfigPath);
                filePath = content;

                Console.WriteLine("文件内容: " + content);
                this.textBox1.Text = content;
            }
            else
            {
                // 文件不存在，创建文件并写入"NULL"
                File.WriteAllText(binConfigPath, "NULL");
                Console.WriteLine("binPath文件不存在，已创建新文件并写入内容");
            }

        }

        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog d = new OpenFileDialog();
            d.Multiselect = true;
            d.Title = "请选择文件";
            d.Filter = "二进制文件(*.bin)|*.bin";
            if (d.ShowDialog() == DialogResult.OK)
            {
                if (d.FileName != "")
                {
                    this.textBox1.Text = d.FileName;
                    filePath = d.FileName;
                    //更新文件
                    File.WriteAllText(binConfigPath, filePath);
                }
                else
                {
                    MessageBox.Show("未选择文件");
                }
            }
        }

        private String generateJsonStr(int filesize, string md5, int ver)
        {
            // 生成JSON
            JObject rootJ = new JObject();
            rootJ["filesize"] = filesize;
            rootJ["md5"] = md5;
            rootJ["ver"] = ver;
            return rootJ.ToString();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            this.richTextBox1.Text = "";
            status = MachineState.E_START_TX;
            timer1.Start();
        }

        private void Uart_Init()
        {
            if (serialPort1.IsOpen) {

                return;
            }
            serialPort1.BaudRate = Convert.ToInt32(baudRate);
            serialPort1.PortName = port;
            serialPort1.DataBits = 8;                       // 数据位8位
            serialPort1.StopBits = StopBits.One;            // 停止位1位
            serialPort1.Parity = Parity.None;               // 校验位无
            serialPort1.Encoding = Encoding.Default;        // 编码方式，默认的就是16进制数据

            serialPort1.Open();
            
        }

        private void update_config_file()
        {
        if (this.textBox2.Text == port && 
            this.textBox3.Text == baudRate)

            return;

            configFile(this.textBox2.Text, this.textBox3.Text);

        }
        private void button2_Click(object sender, EventArgs e)
        {
            //更新配置文件
            update_config_file();

            Uart_Init();

            button2.Enabled = false;
            button4.Enabled = true;
        }

        private void Uart_send_fileInfo()
        {
            // 避免在方法内直接操作UI控件，确保串口已打开
            if (serialPort1 == null || !serialPort1.IsOpen)
            {
                MessageBox.Show("串口未打开，请先打开串口", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            // 检查文件路径是否有效
            if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath))
            {
                MessageBox.Show("文件路径无效或文件不存在", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }


            FileInfo fi = new FileInfo(filePath);
            filesize = (int)fi.Length;
            string info = HeadInfo + generateJsonStr(filesize, "XXX", 4);
            Console.WriteLine("TX>" + info);

            serialPort1.Write(info);
        }





        public static string ProcessString(string input)
        {

            // 1---去除前面4个字符
            string afterRemovingPrefix = input.Substring(4);

            // 找到最后一个'}'的位置
            int lastBraceIndex = afterRemovingPrefix.LastIndexOf('}');

            // 如果找不到'}',返回空字符串
            if (lastBraceIndex == -1)
            {
                return string.Empty;
            }

            // 2----截取到最后一个'}'（包含该字符）
            return afterRemovingPrefix.Substring(0, lastBraceIndex + 1);
        }




        private void Uart_send_fileData()
        {
            try
            {
                // 1. 读取串口数据并解析JSON
                string rxString = serialPort1.ReadExisting();
                if (string.IsNullOrEmpty(rxString) || rxString.Length < 4)
                {
                    //MessageBox.Show("接收数据长度不足，无法处理", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    Console.WriteLine("Error: Invalid serial port data received");
                    return;
                }

                string jsonString = ProcessString(rxString); // 跳过"2###"前缀
                Console.WriteLine($"Received JSON: {jsonString}");

                // 解析JSON数据
                Dictionary<string, int> values = JsonConvert.DeserializeObject<Dictionary<string, int>>(jsonString);
                if (values == null || !values.ContainsKey("addr") || !values.ContainsKey("len"))
                {
                    MessageBox.Show("JSON数据格式错误，缺少必要的键(addr或len)", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                int startAddress = values["addr"];
                int readLen = values["len"];
                Console.WriteLine($"Start Address: {startAddress}, Read Length: {readLen}");

                // 2. 读取文件数据
                using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
                using (var binaryReader = new BinaryReader(fileStream))
                {
                    // 验证文件长度是否足够
                    if (fileStream.Length < startAddress + readLen)
                    {
                        Console.WriteLine("Error: File is too small for requested read");
                        MessageBox.Show("起始地址超出文件范围", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        return;
                    }

                    // 跳过起始地址
                    fileStream.Seek(startAddress, SeekOrigin.Begin);

                    // 读取指定长度的数据
                    byte[] body = binaryReader.ReadBytes(readLen);
                    Console.WriteLine(BitConverter.ToString(body).Replace("-", " "));
                    Console.WriteLine(body);

                    /****************TX业务逻辑*****************/
                    // 准备HEAD

                    byte[] head = System.Text.Encoding.ASCII.GetBytes(HeadData);

                    // 合并头部和数据，避免字符串转换导致的二进制数据错误
                    byte[] sendData = new byte[head.Length + body.Length];
                    Array.Copy(head, 0, sendData, 0, head.Length);
                    Array.Copy(body, 0, sendData, head.Length, body.Length);

                    // 发送数据
                    serialPort1.Write(sendData, 0, sendData.Length);
                    Console.WriteLine($"已发送 {sendData.Length} 字节数据");

                    int sendedSize = (startAddress + readLen) * 100;
                    this.progressBar1.Value = sendedSize / filesize;


                    richTextBox1.AppendText(jsonString + Environment.NewLine);

                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error in Uart_send_fileData: {ex.Message}");
                // 可以根据需要重新抛出异常或处理特定异常类型
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            MachineState curStatus = status;
            status = MachineState.E_IDLE;
            switch (curStatus)
            {
                case MachineState.E_IDLE:
                    return;
                case MachineState.E_START_TX:
                    Uart_send_fileInfo();
                    break;
                case MachineState.E_START_RX:
                    Uart_send_fileData();
                    break;
            }
        }

        private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            status = MachineState.E_START_RX;
        }

        private void button4_Click(object sender, EventArgs e)
        {
            serialPort1.Close();
            button2.Enabled = true;
            button4.Enabled = false;
        }
    }
}
